/*简单工厂模式*/

#include <iostream>
#include <string>
#include <memory>
/*
简单工厂模式实现由一个工厂对象通过类型决定创建出来指定产品类的实例
*/

class Fruit
{
public:
    Fruit() = default;
    virtual void product() = 0;
};

class Apple : public Fruit
{
public:
    Apple() = default;
    virtual void product() override
    {
        std::cout << "我是一个苹果" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    Banana() = default;
    virtual void product() override
    {
        std::cout << "我是一个香蕉" << std::endl;
    }
};

// class FruitFactory
// {
// public:
//     static std::shared_ptr<Fruit> produce(const std::string& demand)
//     {
//         if(demand == "苹果")
//             return std::make_shared<Apple>();
//         else if(demand == "香蕉")
//             return std::make_shared<Banana>();
//         return nullptr;
//     }
// };

// int main()
// {
//     std::shared_ptr<Fruit> a = FruitFactory::produce("苹果");
//     a->product();
//     std::shared_ptr<Fruit> b = FruitFactory::produce("香蕉");
//     b->product();
//     return 0;
// }


/*工厂方法模式*/
// class Factory
// {
// public:
//     Factory() {}
//     virtual std::shared_ptr<Fruit> produce() = 0;
// };

// class AppleFactory : public Factory
// {
// public:
//     AppleFactory() {}
//     virtual std::shared_ptr<Fruit> produce() override
//     {
//         return std::make_shared<Apple>();
//     }
// };

// class BananaFactory : public Factory
// {
// public:
//     BananaFactory() {}
//     virtual std::shared_ptr<Fruit> produce() override
//     {
//         return std::make_shared<Banana>();
//     }
// };

// int main()
// {
//     std::shared_ptr<AppleFactory> af = std::make_shared<AppleFactory>();
//     std::shared_ptr<Fruit> a(af->produce());
//     a->product();

//     std::shared_ptr<BananaFactory> bf(new BananaFactory);
//     std::shared_ptr<Fruit> b(bf->produce());
//     b->product();
//     return 0;
// }


/*抽象工厂的实现*/
class Animal
{
public:
    Animal() {}
    virtual void product() = 0;
};
class Cat : public Animal
{
public:
    Cat() {}
    virtual void product() override
    {
        std::cout << "我是一只猫" << std::endl;
    }
};
class Dog : public Animal
{
public:
    Dog() {}
    virtual void product() override
    {
        std::cout << "我是一条狗" << std::endl;
    }
};

class Factory
{
public:
    Factory() {}
    virtual std::shared_ptr<Fruit> ProduceFruit(const std::string& demand) = 0;
    virtual std::shared_ptr<Animal> ProduceAnimal(const std::string& demand) = 0;
};
class FruitFactory : public Factory
{
public:
    FruitFactory() {}
    virtual std::shared_ptr<Fruit> ProduceFruit(const std::string& demand) override
    {
        if(demand == "苹果")
            return std::make_shared<Apple>();
        else if(demand == "香蕉")
            return std::make_shared<Banana>();
        return std::shared_ptr<Fruit>();
    } 
    virtual std::shared_ptr<Animal> ProduceAnimal(const std::string& demand) override
    {
        return std::shared_ptr<Animal>();
    }
};
class AnimalFactory : public Factory
{
public:
    AnimalFactory() {}
    virtual std::shared_ptr<Fruit> ProduceFruit(const std::string& demand) override
    {
        return std::shared_ptr<Fruit>();
    }
    virtual std::shared_ptr<Animal> ProduceAnimal(const std::string& demand) override
    {
        if(demand == "小猫")
            return std::make_shared<Cat>();
        else if(demand == "小狗")
            return std::make_shared<Dog>();
        return std::shared_ptr<Animal>();
    }
};

class ProduceFactory
{
public:
    ProduceFactory() {}
    static std::shared_ptr<Factory> produce_factory(const std::string& name)
    {
        if(name == "水果工厂")
            return std::make_shared<FruitFactory>();
        else if(name == "动物工厂")
            return std::make_shared<AnimalFactory>();
        return std::shared_ptr<Factory>();
    }
};
int main()
{
    std::shared_ptr<Factory> ff(ProduceFactory::produce_factory("水果工厂"));
    std::shared_ptr<Fruit> a(ff->ProduceFruit("苹果"));
    a->product();

    std::shared_ptr<Fruit> b(ff->ProduceFruit("香蕉"));
    b->product();

    std::shared_ptr<Factory> af(ProduceFactory::produce_factory("动物工厂"));
    std::shared_ptr<Animal> c(af->ProduceAnimal("小猫"));
    c->product();

    std::shared_ptr<Animal> d(af->ProduceAnimal("小狗"));
    d->product();

    std::shared_ptr<Animal> e(af->ProduceAnimal("苹果"));
    if(!e)
        std::cout << "输入错误"  << std::endl;
    return 0;
}
